package com.han.hotelplat.comm.utils.dbutils;

import com.google.common.base.Charsets;
import com.google.common.io.Files;

import javax.sql.DataSource;

import java.io.BufferedWriter;
import java.io.File;
import java.io.PrintWriter;
import java.io.Serializable;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

/**
 * PO打印机4.2
 *
 * @author chao
 *
 */
public class PoPrinter {

	/**
	 * 打印
	 *
	 * @param ds
	 *            数据源
	 * @param printPath
	 *            打印路径
	 * @param packageName
	 *            希望打印的包名
	 *
	 * 打印结果会按照TbNamePO命名
	 */
	public static void print(DataSource ds, String printPath,
							 String packageName) throws Exception {

		try {
			System.out.println("打印路径："+printPath+",希望打印的包名:"+packageName);
			
			Connection conn = ds.getConnection();

			ResultSet tbRs = conn.getMetaData().getTables(null, null, null, null);

			List<String> tbNames = new LinkedList<>();

			while(tbRs.next()) {
				tbNames.add(tbRs.getString("TABLE_NAME"));
			}

			for (String tbName : tbNames) {
				ResultSet rs = conn.getMetaData().getColumns(null, null, tbName, null);
				String poName = StringUtils.underlineToUpperCamal(tbName);
				String basePoName = poName.substring("Tb".length());;

				List<String> colNames = new ArrayList<>();
				List<String> colTypes = new ArrayList<>();
				List<String> staticColNames = new ArrayList<>();
				List<String> remarks = new ArrayList<>();
				List<String> defaults = new ArrayList<>();

				while (rs.next()) {
					String cname = rs.getString("COLUMN_NAME");
					String ctype = rs.getString("TYPE_NAME");
					ctype = sqlTypeToJavaType(ctype);
					colNames.add(StringUtils.underlineToLowerCamal(cname));
					colTypes.add(ctype);
					staticColNames.add("PROP_"+StringUtils.camalToUnderline(cname).toUpperCase());
					remarks.add(rs.getString("REMARKS"));

					String def = rs.getString("COLUMN_DEF");
					if (def != null) {
						if (ctype.contains("Long")) {
							def += "L";
						}

						if (ctype.contains("String")) {
							def = "\"" + def + "\"";
						}
					}

					defaults.add(def);
				}

				// 检查路径
				DirUtils.mkdir(printPath + File.separator + "base");

				// 开始打印base类
				BufferedWriter writer = Files.newWriter(new File(printPath + File.separator + "base" + File.separator + basePoName + ".java"), Charsets.UTF_8);
				PrintWriter out = new PrintWriter(writer);
				out.println("package "+packageName +"."+basePoName.toLowerCase()+";");
				out.println();
				out.println("import java.io.Serializable;");
				out.println();
				
				out.println("/**");
				out.println(" * @author han1088");
				out.println(" */");
				out.println("public class " + basePoName + " implements Serializable {");
				out.println();
				// 打印对象字段
				for (int i = 0; i < colNames.size(); i++) {
					out.println("\t/**"+remarks.get(i)+"*/");
					out.println("\tprivate " + colTypes.get(i) + " " + colNames.get(i) + " = " + defaults.get(i) + ";" );
				}
				out.println();
				
				//打印缺省构造
				out.println("\tpublic " + basePoName + "()" + "{ ");
				out.println("\t}");
				out.println();
				
				//打印全字段构造
				String printData = "\tpublic " + basePoName + "(";
				for(int i=0; i < colNames.size()-1; i++){
					printData = printData + colTypes.get(i) + " " + colNames.get(i) + ",";
				}
				printData = printData+ colTypes.get(colNames.size()-1) + " " + colNames.get(colNames.size()-1)  + ")";
				out.println(printData+ "{ ");
				out.println("\t}");
				out.println();
				
				// 打印getset
				for (int i = 0; i < colNames.size(); i++) {
					out.println("\t/**get "+remarks.get(i)+"*/");
					out.println("\tpublic " + colTypes.get(i) + " get" + StringUtils.upFirst1(colNames.get(i)) + "(){");
					out.println("\t\treturn " + colNames.get(i) + ";");
					out.println("\t}");
					out.println();

					out.println("\t/**set "+remarks.get(i)+"*/");
					out.println("\tpublic void set" + StringUtils.upFirst1(colNames.get(i)) + "(" + colTypes.get(i) + " " + colNames.get(i) + "){");
					out.println("\t\tthis." + colNames.get(i) + " = " + colNames.get(i) + ";");
					out.println("\t}");
					out.println();
				}

				out.println("}");
				out.close();
				writer.close();
				System.out.println("生成表："+conn.getCatalog()+"."+tbName);
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}

	}

	private static String sqlTypeToJavaType(String type){

		if(type.equals("BIGINT")){
			return "java.lang.Long";
		}
		if(type.equals("SMALLINT")){
			return "java.lang.Short";
		}
		if(type.contains("INT")){
			return "java.lang.Integer";
		}
		if(type.equals("FLOAT")){
			return "java.lang.Float";
		}
		if(type.equals("DOUBLE")){
			return "java.lang.Float";
		}
		if(type.contains("CHAR") || type.contains("TEXT")){
			return "java.lang.String";
		}
		if(type.contains("BINARY") || type.contains("BLOB")){
			return "byte[]";
		}
		if(type.contains("DATE") || type.contains("TIME")){
			return "java.util.Date";
		}

		// 其他类型拜托不要用了
		throw new RuntimeException("unsupported type = " + type);
	}

}